{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ConversationSummaryMemory\n",
    "\n",
    "이제 조금 더 복잡한 메모리 유형인 `ConversationSummaryMemory` 를 사용하는 방법을 살펴 보겠습니다.\n",
    "\n",
    "이 유형의 메모리는 시간 경과에 따른 **대화의 요약** 을 생성합니다. 이는 시간 경과에 따른 대화의 정보를 압축하는 데 유용할 수 있습니다.\n",
    "\n",
    "대화 요약 메모리는 대화가 진행되는 동안 대화를 요약하고 **현재 요약을 메모리에 저장** 합니다.\n",
    "\n",
    "그런 다음 이 메모리를 사용하여 지금까지의 대화 요약을 프롬프트/체인에 삽입할 수 있습니다.\n",
    "\n",
    "이 메모리는 과거 메시지 기록을 프롬프트에 그대로 보관하면 토큰을 너무 많이 차지할 수 있는 긴 대화에 가장 유용합니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`ConversationSummaryMemory` 를 생성합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# API KEY를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API KEY 정보로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.memory import ConversationSummaryMemory\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "memory = ConversationSummaryMemory(\n",
    "    llm=ChatOpenAI(model_name=\"gpt-4.1-mini\", temperature=0), return_messages=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "여러 대화를 저장하도록 합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context(\n",
    "    inputs={\"human\": \"유럽 여행 패키지의 가격은 얼마인가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"유럽 14박 15일 패키지의 기본 가격은 3,500유로입니다. 이 가격에는 항공료, 호텔 숙박비, 지정된 관광지 입장료가 포함되어 있습니다. 추가 비용은 선택하신 옵션 투어나 개인 경비에 따라 달라집니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"여행 중에 방문할 주요 관광지는 어디인가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"이 여행에서는 파리의 에펠탑, 로마의 콜로세움, 베를린의 브란덴부르크 문, 취리히의 라이네폴 등 유럽의 유명한 관광지들을 방문합니다. 각 도시의 대표적인 명소들을 포괄적으로 경험하실 수 있습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"여행자 보험은 포함되어 있나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"네, 모든 여행자에게 기본 여행자 보험을 제공합니다. 이 보험은 의료비 지원, 긴급 상황 발생 시 지원 등을 포함합니다. 추가적인 보험 보장을 원하시면 상향 조정이 가능합니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"항공편 좌석을 비즈니스 클래스로 업그레이드할 수 있나요? 비용은 어떻게 되나요?\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"항공편 좌석을 비즈니스 클래스로 업그레이드하는 것이 가능합니다. 업그레이드 비용은 왕복 기준으로 약 1,200유로 추가됩니다. 비즈니스 클래스에서는 더 넓은 좌석, 우수한 기내식, 그리고 추가 수하물 허용량 등의 혜택을 제공합니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"패키지에 포함된 호텔의 등급은 어떻게 되나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"이 패키지에는 4성급 호텔 숙박이 포함되어 있습니다. 각 호텔은 편안함과 편의성을 제공하며, 중심지에 위치해 관광지와의 접근성이 좋습니다. 모든 호텔은 우수한 서비스와 편의 시설을 갖추고 있습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"식사 옵션에 대해 더 자세히 알려주실 수 있나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"이 여행 패키지는 매일 아침 호텔에서 제공되는 조식을 포함하고 있습니다. 점심과 저녁 식사는 포함되어 있지 않아, 여행자가 자유롭게 현지의 다양한 음식을 경험할 수 있는 기회를 제공합니다. 또한, 각 도시별로 추천 식당 리스트를 제공하여 현지의 맛을 최대한 즐길 수 있도록 도와드립니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"패키지 예약 시 예약금은 얼마인가요? 취소 정책은 어떻게 되나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"패키지 예약 시 500유로의 예약금이 필요합니다. 취소 정책은 예약일로부터 30일 전까지는 전액 환불이 가능하며, 이후 취소 시에는 예약금이 환불되지 않습니다. 여행 시작일로부터 14일 전 취소 시 50%의 비용이 청구되며, 그 이후는 전액 비용이 청구됩니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "저장된 메모리의 history 를 확인합니다.\n",
    "\n",
    "이전의 모든 대화를 압축적으로 요약한 내용을 확인할 수 있습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 저장된 메모리 확인\n",
    "print(memory.load_memory_variables({})[\"history\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ConversationSummaryBufferMemory\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`ConversationSummaryBufferMemory` 는 두 가지 아이디어를 결합한 것입니다.\n",
    "\n",
    "최근 대화내용의 버퍼를 메모리에 유지하되, 이전 대화내용을 완전히 플러시(flush)하지 않고 요약으로 컴파일하여 두 가지를 모두 사용합니다.\n",
    "\n",
    "대화내용을 플러시할 시기를 결정하기 위해 상호작용의 개수가 아닌 **토큰 길이** 를 사용합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.memory import ConversationSummaryBufferMemory\n",
    "\n",
    "llm = ChatOpenAI()\n",
    "\n",
    "memory = ConversationSummaryBufferMemory(\n",
    "    llm=llm,\n",
    "    max_token_limit=200,  # 요약의 기준이 되는 토큰 길이를 설정합니다.\n",
    "    return_messages=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "먼저, 1개의 대화만 저장해 보도록 한 뒤, 메모리를 확인해 보겠습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context(\n",
    "    inputs={\"human\": \"유럽 여행 패키지의 가격은 얼마인가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"유럽 14박 15일 패키지의 기본 가격은 3,500유로입니다. 이 가격에는 항공료, 호텔 숙박비, 지정된 관광지 입장료가 포함되어 있습니다. 추가 비용은 선택하신 옵션 투어나 개인 경비에 따라 달라집니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "메모리에 저장된 대화를 확인합니다.\n",
    "\n",
    "아직은 대화내용을 요약하지 않습니다. 기준이 되는 **200** 토큰에 도달하지 않았기 때문입니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 메모리에 저장된 대화내용 확인\n",
    "memory.load_memory_variables({})[\"history\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "대화를 추가로 저장하여 200 토큰 제한을 넘기도록 해 보겠습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context(\n",
    "    inputs={\"human\": \"여행 중에 방문할 주요 관광지는 어디인가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"이 여행에서는 파리의 에펠탑, 로마의 콜로세움, 베를린의 브란덴부르크 문, 취리히의 라이네폴 등 유럽의 유명한 관광지들을 방문합니다. 각 도시의 대표적인 명소들을 포괄적으로 경험하실 수 있습니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"여행자 보험은 포함되어 있나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"네, 모든 여행자에게 기본 여행자 보험을 제공합니다. 이 보험은 의료비 지원, 긴급 상황 발생 시 지원 등을 포함합니다. 추가적인 보험 보장을 원하시면 상향 조정이 가능합니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"항공편 좌석을 비즈니스 클래스로 업그레이드할 수 있나요? 비용은 어떻게 되나요?\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"항공편 좌석을 비즈니스 클래스로 업그레이드하는 것이 가능합니다. 업그레이드 비용은 왕복 기준으로 약 1,200유로 추가됩니다. 비즈니스 클래스에서는 더 넓은 좌석, 우수한 기내식, 그리고 추가 수하물 허용량 등의 혜택을 제공합니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"패키지에 포함된 호텔의 등급은 어떻게 되나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"이 패키지에는 4성급 호텔 숙박이 포함되어 있습니다. 각 호텔은 편안함과 편의성을 제공하며, 중심지에 위치해 관광지와의 접근성이 좋습니다. 모든 호텔은 우수한 서비스와 편의 시설을 갖추고 있습니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "저장된 대화내용을 확인합니다. 가장 최근 1개의 대화에 대해서는 요약이 진행되지 않지만, 이전의 대화내용은 요약본으로 저장되어 있습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 메모리에 저장된 대화내용 확인\n",
    "memory.load_memory_variables({})[\"history\"]"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
